/*
 * Copyright (C) 2013 AndXmppSDK Project <hljdrl@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.drl.xmpp;

import java.util.ArrayList;
import java.util.List;

import org.drl.xmpp.storage.table.MessageTable;
import org.drl.xmpp.util.StringHelper;
import org.drl.xmpp.util.StringUtils2;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.ChatState;
import org.jivesoftware.smackx.ChatStateListener;
import org.jivesoftware.smackx.workgroup.packet.SessionID;

/**
 * @author hljdrl@gmail.com
 * 
 */
public final class TChat implements ChatStateListener {

	private final Chat mChat;
	private final Contact mParticipant;

	private String mState;
	private boolean mIsOpen;

	private SessionID mOtrSessionId;
	private List<MessageListener> messageListeners = new ArrayList<MessageListener>();
	private UserInfo user;
	private TalkClient mTalk;

	/**
	 * @param chat
	 * @param tc
	 */
	public TChat(final Chat chat, TalkClient tc) {
		mChat = chat;
		mParticipant = new Contact(chat.getParticipant());
		mChat.addMessageListener(this);
		mTalk = tc;
		user = mTalk.getUserInfo();
	}

	/**
	 * @param message
	 */
	public final boolean sendMessage(TMessage message) {
		TMessage encrypted = otrEncryptMessage(message);
		if (encrypted == null) {
			encrypted = message;
		}
		try {
			transferMessage(encrypted);
			return true;
		} catch (XMPPException xe) {
			xe.printStackTrace();
			return false;
		}

	}

	private boolean transferMessage(TMessage message) throws XMPPException {
		org.jivesoftware.smack.packet.Message send = new org.jivesoftware.smack.packet.Message();
		String msgBody = message.getBody();
		send.setTo(message.getTo());
		send.setBody(msgBody);
		send.setThread(message.getThread());
		send.setSubject(message.getSubject());
		send.setType(org.jivesoftware.smack.packet.Message.Type.chat);
		try {
			mChat.sendMessage(send);
			// 保存聊天记录
			addMesage(message);
			return true;
		} catch (XMPPException e) {
			e.printStackTrace();
			throw e;
		}
	}

	private TMessage otrEncryptMessage(TMessage unencrypted) {
		return null;
	}

	/**
	 * @return
	 */
	public final Contact getParticipant() {
		return mParticipant;
	}

	/**
	 * @param listener
	 */
	public final void addMessageListener(MessageListener listener) {
		if (listener != null) {
			messageListeners.add(listener);
		}
	}

	/**
	 * @param listener
	 */
	public final void removeMessageListener(MessageListener listener) {
		messageListeners.remove(listener);
	}

	public final String getState() {
		return mState;
	}

	public final void setOpen(boolean isOpen) {
		this.mIsOpen = isOpen;
	}

	public final boolean isOpen() {
		return mIsOpen;
	}

	public final void setState(String state) {
		this.mState = state;
	}

	void addMesage(TMessage mMsg) {
		if (mMsg != null && StringHelper.isText(mMsg.getBody())) {
			logMessage(mMsg);
		}
	}

	private void logMessage(TMessage mMsg) {
		saveHistory(mMsg, user);
	}

	private void saveHistory(TMessage mMsg, UserInfo user) {
		String form = StringUtils2.parseName(mMsg.getFrom());
		String useJid = StringUtils2.parseName(user.getJid());

		if (StringHelper.isText(form) && form.equals(useJid)) {
			// 判断是用户发出的消息，存到数据库中是已读信息.
			MessageTable table = MessageTable.getInstance();
			mMsg.setRead(true);
			table.write(mMsg, user);
		} else {
			mMsg.setRead(mIsOpen);
			MessageTable table = MessageTable.getInstance();
			table.write(mMsg, user);
		}
	}

	// -----------------------------------------------------------

	@Override
	public void processMessage(Chat arg0, Message arg1) {
		TMessage tMt = new TMessage(arg1);
		TChat.this.addMesage(tMt);
	}

	@Override
	public void stateChanged(Chat arg0, ChatState state) {
		mState = state.name();
	}

}
